home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tape / RCS / tape.c,v < prev    next >
Text File  |  1992-08-09  |  11KB  |  456 lines

  1. head     1.7;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.7
  10. date     92.08.09.18.05.59;  author mottsmth;  state Exp;
  11. branches ;
  12. next     1.6;
  13.  
  14. 1.6
  15. date     92.07.22.18.26.07;  author jhh;  state Exp;
  16. branches ;
  17. next     1.5;
  18.  
  19. 1.5
  20. date     91.09.03.17.33.39;  author jhh;  state Exp;
  21. branches ;
  22. next     1.4;
  23.  
  24. 1.4
  25. date     90.06.28.15.15.42;  author jhh;  state Exp;
  26. branches ;
  27. next     1.3;
  28.  
  29. 1.3
  30. date     90.03.21.17.38.06;  author jhh;  state Exp;
  31. branches ;
  32. next     1.2;
  33.  
  34. 1.2
  35. date     90.03.21.17.32.49;  author mendel;  state Exp;
  36. branches ;
  37. next     1.1;
  38.  
  39. 1.1
  40. date     89.04.22.16.59.32;  author mendel;  state Exp;
  41. branches ;
  42. next     ;
  43.  
  44.  
  45. desc
  46. @Checked in for Brent.
  47. @
  48.  
  49.  
  50. 1.7
  51. log
  52. @Add inquiry option
  53. @
  54. text
  55. @/*
  56.  * tape.c --
  57.  *    Manipulate a tape drive.
  58.  */
  59. #include "sprite.h"
  60. #include "status.h"
  61. #include "time.h"
  62. #include "sys/file.h"
  63. #include "fs.h"
  64. #include "dev/tape.h"
  65. #include <dev/scsi.h>
  66. #include <sys/scsi.h>
  67. #include "stdio.h"
  68. #include "option.h"
  69. #include "errno.h"
  70. #include "tape.h"
  71.  
  72. char *tapeFile = "/dev/tape0";
  73. Boolean rewindIt = FALSE;
  74. Boolean retension = FALSE;
  75. Boolean gotoEnd = FALSE;
  76. Boolean readIt = FALSE;
  77. Boolean erase = FALSE;
  78. int skipFiles = 0;
  79. int skipBlocks = 0;
  80. int writeIt = 0;
  81. int blockSize = 16 * 1024;
  82. int weof = 0;
  83. int gotoBlock = -1;
  84. Boolean doStatus = FALSE;
  85. Boolean load = FALSE;
  86. Boolean unload = FALSE;
  87. Boolean prevent = FALSE;
  88. Boolean allow = FALSE;
  89. Boolean inquiry = FALSE;
  90.  
  91. Option optionArray[] = {
  92.     { OPT_STRING, "t", (Address)&tapeFile, "Name of tape device" },
  93.     { OPT_TRUE, "r", (Address)&rewindIt, "Rewind the tape" },
  94.     { OPT_TRUE, "T", (Address)&retension, "Retension the tape" },
  95.     { OPT_TRUE, "e", (Address)&gotoEnd, "Skip to the end of data." },
  96.     { OPT_INT, "f", (Address)&skipFiles, "Number of tape files to skip" }, 
  97.     { OPT_INT, "b", (Address)&skipBlocks, "Number of blocks to skip" }, 
  98.     { OPT_INT, "m", (Address)&weof, "Number of end-of-file marks to write" }, 
  99.     { OPT_INT, "B", (Address)&blockSize, "Block size" },
  100.     { OPT_TRUE, "R", (Address)&readIt, "Read til end of file"},
  101.     { OPT_INT, "W",  (Address)&writeIt, "Write -W N blocks"},
  102.     { OPT_TRUE, "E",  (Address)&erase, "Erase the whole tape!"},
  103.     { OPT_INT, "g", (Address) &gotoBlock, "Goto block N"},
  104.     { OPT_TRUE, "s", (Address) &doStatus, "Print tape status"},
  105.     { OPT_TRUE, "l", (Address) &load, "Load tape"},
  106.     { OPT_TRUE, "u", (Address) &unload, "Unload tape"},
  107.     { OPT_TRUE, "p", (Address) &prevent, "Prevent tape removal"},
  108.     { OPT_TRUE, "a", (Address) &allow, "Allow tape removal"},
  109.     { OPT_TRUE, "i", (Address) &inquiry, "Perform tape inquiry"}
  110. };
  111. int numOptions = sizeof(optionArray) / sizeof(Option);
  112.  
  113. main(argc, argv)
  114. int argc;
  115. char **argv;
  116. {
  117.     int oldOffset;
  118.     ReturnStatus status;
  119.     int tapeStream;
  120.     Address buffer;
  121.     int amountRead, amountWritten, total;
  122.     int openFlags;
  123.  
  124.     argc = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  125.  
  126.     if (writeIt || weof) {
  127.     openFlags = O_RDWR;
  128.     } else {
  129.     openFlags = O_RDONLY;
  130.     }
  131.     tapeStream = open(tapeFile, openFlags, 0);
  132.     if (tapeStream < 0) {
  133.     perror("Can't open tape drive");
  134.     exit(errno);
  135.     }
  136.     buffer = (Address)malloc(blockSize);
  137.     if (inquiry) {
  138.     status = Inquiry(tapeStream);
  139.     if (status != SUCCESS) {
  140.         Stat_PrintMsg(status, "Can't perform inquiry");
  141.         exit(status);
  142.     }
  143.     }
  144.  
  145.     if (retension) {
  146.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_RETENSION, 1);
  147.     if (status != SUCCESS) {
  148.         Stat_PrintMsg(status, "Can't retension tape");
  149.         exit(status);
  150.     }
  151.     }
  152.  
  153.     if (gotoEnd) {
  154.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_SKIP_EOD, 0);
  155.     if (status != SUCCESS) {
  156.         Stat_PrintMsg(status, "Can't position at end-of-tape");
  157.         exit(status);
  158.     }
  159.     }
  160.     if (rewindIt) {
  161.     status = Ioc_Reposition(tapeStream, IOC_BASE_ZERO, 0, &oldOffset);
  162.     if (status != SUCCESS) {
  163.         Stat_PrintMsg(status, "Can't rewind tape drive");
  164.         exit(status);
  165.     }
  166.     }
  167.     if (erase) {
  168.     char answer[40];
  169.     printf("Really erase the tape? ");
  170.     scanf(" %s", answer);
  171.     if (answer[0] == 'y' || answer[0] == 'Y') {
  172.         printf("Ok, here goes\n");
  173.         status = Ioc_TapeCommand(tapeStream, IOC_TAPE_ERASE, 0);
  174.         if (status != SUCCESS) {
  175.         Stat_PrintMsg(status, "Can't erase tape");
  176.         exit(status);
  177.         }
  178.     } else {
  179.         printf("Ok, not erasing\n");
  180.     }
  181.     }
  182.     if (skipFiles) {
  183.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_SKIP_FILES, skipFiles);
  184.     if (status != SUCCESS) {
  185.         Stat_PrintMsg(status, "Can't skip tape files");
  186.         exit(status);
  187.     }
  188.     } else if (skipBlocks > 0) {
  189.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_SKIP_BLOCKS, skipBlocks);
  190.     if (status != SUCCESS) {
  191.         Stat_PrintMsg(status, "Can't skip tape blocks");
  192.         exit(status);
  193.     }
  194.     }
  195.     if (weof) {
  196.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_WEOF, weof);
  197.     if (status != SUCCESS) {
  198.         Stat_PrintMsg(status, "Can't write file mark(s)");
  199.         exit(status);
  200.     }
  201.     }
  202.  
  203.     if (writeIt > 0) {
  204.     total = 0;
  205.     while (writeIt-- > 0) {
  206.         amountWritten = write(tapeStream, buffer, blockSize);
  207.         if (amountWritten < 0) {
  208.         break;
  209.         }
  210.         total += amountWritten;
  211.         if (amountWritten < blockSize) {
  212.         break;
  213.         }
  214.     }
  215.     fprintf(stderr, "Wrote %d bytes\n", total);
  216.     if (amountWritten < 0) {
  217.         perror("Tape write failed");
  218.     }
  219.     } else if (readIt) {
  220.     total = 0;
  221.     while (1) {
  222.         amountRead = read(tapeStream, buffer, blockSize, buffer);
  223.         if (amountRead <= 0) {
  224.         break;
  225.         }
  226.         total += amountRead;
  227.     }
  228.     if (amountRead < 0) {
  229.         perror("Tape read failed");
  230.     }
  231.     fprintf(stderr, "Read %d bytes\n", total);
  232.     }
  233.     if (gotoBlock != -1) {
  234.         status = Ioc_TapeCommand(tapeStream, IOC_TAPE_GOTO_BLOCK, gotoBlock);
  235.     if (status != SUCCESS) {
  236.         Stat_PrintMsg(status, "Can't goto block");
  237.         exit(status);
  238.     }
  239.     }
  240.     if (doStatus) {
  241.     Dev_TapeStatus    tapeStatus;
  242.     bzero((char *) &tapeStatus, sizeof(tapeStatus));
  243.     status = Fs_IOControl(tapeStream, IOC_TAPE_STATUS, 0, NULL, 
  244.         sizeof(tapeStatus), &tapeStatus);
  245.     if (status != SUCCESS) {
  246.         Stat_PrintMsg(status, "Can't get status");
  247.         exit(status);
  248.     }
  249.     printf("Type : 0x%x\n", tapeStatus.type);
  250.     printf("Serial : %s\n", tapeStatus.serial);
  251.     printf("Block size : %d\n", tapeStatus.blockSize);
  252.     printf("Current block : %d\n", tapeStatus.position);
  253.     printf("Remaining blocks : %d\n", tapeStatus.remaining);
  254.     printf("Data errors : %d\n", tapeStatus.dataError);
  255.     printf("Read/Write retry : %d\n", tapeStatus.readWriteRetry);
  256.     printf("Tracking retry : %d\n", tapeStatus.trackingRetry);
  257.     printf("Write protect : %d\n", tapeStatus.writeProtect);
  258.     printf("Buffered mode : %d\n", tapeStatus.bufferedMode);
  259.     printf("Speed : %d\n", tapeStatus.speed);
  260.     printf("Density : %d\n", tapeStatus.density);
  261.     }
  262.     if (load) {
  263.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_LOAD, 0);
  264.     if (status != SUCCESS) {
  265.         Stat_PrintMsg(status, "Can't load tape");
  266.         exit(status);
  267.     }
  268.     }
  269.     if (unload) {
  270.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_UNLOAD, 0);
  271.     if (status != SUCCESS) {
  272.         Stat_PrintMsg(status, "Can't unload tape");
  273.         exit(status);
  274.     }
  275.     }
  276.     if (prevent) {
  277.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_PREVENT_REMOVAL, 0);
  278.     if (status != SUCCESS) {
  279.         Stat_PrintMsg(status, "Can't prevent tape removal");
  280.         exit(status);
  281.     }
  282.     }
  283.     if (allow) {
  284.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_ALLOW_REMOVAL, 0);
  285.     if (status != SUCCESS) {
  286.         Stat_PrintMsg(status, "Can't allow tape removal");
  287.         exit(status);
  288.     }
  289.     }
  290.     close(tapeStream);
  291.     fprintf(stderr, "done\n");
  292.     exit(SUCCESS);
  293. }
  294.  
  295. static int
  296. Inquiry(fd)
  297. int fd;
  298. {
  299.     int status;
  300.     char buf[80];
  301.  
  302.     struct InCmd {
  303.     Dev_ScsiCommand hdr;
  304.     InquiryCommand cmd;    
  305.     } inCmd; 
  306.  
  307.     struct OutStatus {
  308.     Dev_ScsiStatus hdr;
  309.     struct InquiryData {
  310. #if BYTE_ORDER == BIG_ENDIAN
  311.         unsigned char type;         /* Peripheral device type */
  312.         unsigned char rmb:1;        /* Removable Medium bit. */
  313.         unsigned char qualifier:7;  /* Device type qualifier. */
  314.         unsigned char version;      /* Version info. */
  315.         unsigned char reserved:4;   /* reserved. */
  316.         unsigned char format:4;     /* Response format. */
  317. #else /* BYTE_ORDER == LITTLE_ENDIAN */
  318.         unsigned char type;        /* Peripheral device type. */
  319.         unsigned char qualifier:7;    /* Device Type qualifier. */
  320.         unsigned char rmb:1;    /* Removable Medium bit. */
  321.         unsigned char version;    /* Version info. */
  322.         unsigned char format:4;    /* Response format */
  323.         unsigned char reserved:4;    /* reserved. */
  324. #endif
  325.         unsigned char length;         /* Additional length of data returned. */
  326.         unsigned char reserved2[3];   /* More reserved and not supported. */
  327.         char          vendorID[8];  /* Vector identification. */
  328.         char          productID[16]; /* Product identification. */
  329.         char          revLevel[4]; /* Firmware identification. */
  330.         unsigned char reserved3[20];  /* More reserved. */
  331.     } inquiryData; 
  332.     } outStatus;
  333.  
  334.     memset(&inCmd, 0, sizeof(inCmd));
  335.     memset(&outStatus, 0, sizeof(outStatus));
  336.     
  337.     inCmd.hdr.bufferLen = sizeof(struct InquiryData);
  338.     inCmd.hdr.commandLen = sizeof(InquiryCommand);
  339.     inCmd.hdr.dataOffset = sizeof(Dev_ScsiCommand) + sizeof(InquiryCommand);
  340.  
  341. /* Fill in Command Descriptor Block. */
  342.  
  343.     inCmd.cmd.command = SCSI_INQUIRY;
  344.     inCmd.cmd.unitNumber = 0;    /* For our purposes, the unitNumber is always
  345.                  * zero. 
  346.                  */
  347.     inCmd.cmd.evpd = 0;        /* The EXB-120 only supports 0 for this field. */
  348.     inCmd.cmd.allocLength = 0x38;
  349.     inCmd.cmd.link = 0;
  350.     inCmd.cmd.flag = 0;
  351.     inCmd.cmd.vendorUnique = 0;
  352.     
  353.     status = Fs_IOControl(fd, IOC_SCSI_COMMAND,
  354.               inCmd.hdr.dataOffset, (void *) &inCmd,
  355.               sizeof(outStatus), (void *) &outStatus);
  356.  
  357.     printf("Scsi status byte = 0x%x\n", outStatus.hdr.statusByte);
  358.     printf("Scsi transfer len = %d\n", outStatus.hdr.amountTransferred);
  359.     printf("Scsi senseData len = %d\n", outStatus.hdr.senseDataLen);
  360.  
  361.     strncpy(buf,outStatus.inquiryData.vendorID,
  362.         sizeof(outStatus.inquiryData.vendorID));
  363.     *(buf+sizeof(outStatus.inquiryData.vendorID)) = '\0';
  364.     printf("Vendor ID = %s\n", buf);
  365.     strncpy(buf,outStatus.inquiryData.productID,
  366.         sizeof(outStatus.inquiryData.productID));
  367.     *(buf+sizeof(outStatus.inquiryData.productID)) = '\0';
  368.     printf("Product ID = %s\n", buf);
  369.     strncpy(buf,outStatus.inquiryData.revLevel,
  370.         sizeof(outStatus.inquiryData.revLevel));
  371.     *(buf+sizeof(outStatus.inquiryData.revLevel)) = '\0';
  372.     printf("Rev level = %s\n", buf);
  373.  
  374.     return status;
  375. }
  376.  
  377. @
  378.  
  379.  
  380. 1.6
  381. log
  382. @added skip to end-of-data
  383. @
  384. text
  385. @d11 2
  386. d16 1
  387. d35 1
  388. d55 1
  389. d83 8
  390. d240 83
  391. @
  392.  
  393.  
  394. 1.5
  395. log
  396. @added a bunch of new options
  397. @
  398. text
  399. @d87 1
  400. a87 1
  401.     status = Ioc_Reposition(tapeStream, IOC_BASE_EOF, 0, &oldOffset);
  402. @
  403.  
  404.  
  405. 1.4
  406. log
  407. @the -m option was goofed up
  408. @
  409. text
  410. @d26 6
  411. d37 1
  412. a37 1
  413.     { OPT_TRUE, "e", (Address)&gotoEnd, "Skip to the end of the tape" },
  414. d45 6
  415. d165 57
  416. @
  417.  
  418.  
  419. 1.3
  420. log
  421. @exits with 0 status if no error
  422. @
  423. text
  424. @d34 1
  425. a34 1
  426.     { OPT_INT, "m", (Address)&skipBlocks, "Number of end-of-file marks to write" }, 
  427. @
  428.  
  429.  
  430. 1.2
  431. log
  432. @*** empty log message ***
  433. @
  434. text
  435. @d156 1
  436. @
  437.  
  438.  
  439. 1.1
  440. log
  441. @Initial revision
  442. @
  443. text
  444. @d21 3
  445. a23 3
  446. int skipFiles = -1024;    /* funny initial value because back skipping is ok */
  447. int skipBlocks = -1;
  448. int writeIt = -1;
  449. d25 1
  450. a25 1
  451. int weof = -1;
  452. d103 1
  453. a103 1
  454.     if (skipFiles != -1024) {
  455. @
  456.